<template>
    <div class="particle">
        <canvas id="canvas"></canvas>
    </div>
</template>
<script setup>
import { nextTick } from 'vue';

nextTick(() => {
    const canvas = document.querySelector('canvas');
    const ctx = canvas.getContext('2d', {
        willReadFrequently: true //表示 将频繁读取画布
    })

    function initCanvasSize() {
        canvas.width = window.innerWidth * devicePixelRatio;
        canvas.height = window.innerHeight * devicePixelRatio;
    }

    initCanvasSize();

    function getRandom(min, max) {
        return Math.floor(Math.random() * (max + 1 - min) + min); 		//The maximum is inclusive and the minimum is inclusive
    }
    //画一个圆
    class Particle {
        //生成颗粒 
        constructor() {
            const r = Math.min(canvas.width, canvas.height) / 2; //圆的半径 来自canvas的宽高最小值/2
            const cx = canvas.width / 2; //圆的中心 来自canvas的宽高最小值/2
            const cy = canvas.height / 2; //圆的中心 来自canvas的宽高最小值/2
            const rad = getRandom(0, 360) * Math.PI / 180; //生成一个0-360度的角 用于坐标移动
            this.x = cx + r * Math.cos(rad); //根据生成球的方法生成球的x坐标 用于移动球
            this.y = cy + r * Math.sin(rad); //根据生成球的方法生成球的y坐标 用于移
            this.size = getRandom(2 * devicePixelRatio, 6 * devicePixelRatio); //生成一个随机的球半径 用于球的显示 也就是说，球的深度随机 也
        }
        draw() { //画出一个球 参数是一个实数 这个实数代表了球的深度
            ctx.beginPath(); //Start a new path 创建一个新的路径 可以画出球的一个框 也可以画一个
            ctx.fillStyle = '#5445544d'
            ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI); //Draw a circle with
            ctx.fill();
        }
        //位置的移动
        moveTo(tx, ty) {
            const duration = 500;
            const sx = this.x,
                sy = this.y;
            const xSpeed = (tx - sx) / duration;
            const ySpeed = (ty - sy) / duration;
            const startTime = Date.now();
            const __move = () => {
                const t = Date.now() - startTime; //运动了多少时间
                const x = sx + xSpeed * t;
                const y = sy + ySpeed * t;
                this.x = x;
                this.y = y;
                if (t >= duration) {
                    this.x = tx;
                    this.y = ty;
                    return;
                }
                requestAnimationFrame(__move)
            }
            __move();
        }
    }
    const partciles = []; //用于存储坐标点

    let text = null;
    const p = new Particle();
    partciles.push(p);

    function clear() {
        ctx.clearRect(0, 0, canvas.width, canvas.height); //Clears the canvas
    }
    function draw() {
        clear();
        update();
        partciles.forEach((p) => p.draw())
        requestAnimationFrame(draw)
    }
    draw()
    function getText() {
        return new Date().toTimeString().substring(0, 8); //Gets the time and converts it to a string with the format "YYYY-MM-DD hh:
    }

    function update() {
        const newText = getText()
        if (newText === text) {
            return;
        }
        text = newText;
        //画文本
        const { width, height } = canvas;
        ctx.fillStyle = "#000"; //Dark blue background for the text. 描述了
        ctx.textBaseline = 'middle'
        ctx.font = `${140 * devicePixelRatio}px 'DS-Digital',sans-serif`;
        // ctx.measureText(text).width; //获取文本的宽度
        ctx.fillText(text, (width - ctx.measureText(text).width) / 2, height / 2)
        const points = getPoints();
        clear()
        for (let i = 0; i < points.length; i++) {
            let p = partciles[i];
            if (!p) {
                p = new Particle();
                partciles.push(p)
            }
            const [x, y] = points[i];
            p.moveTo(x, y)
        }
        if (points.length < partciles.length) {
            partciles.splice(points.length)
        }
    }
    function getPoints() {
        const points = [];
        const gap = 6;
        const { width, height, data } = ctx.getImageData(0, 0, canvas.width, canvas.height); //获取所有像素点
        for (let i = 0; i < width; i += gap) {
            for (let j = 0; j < height; j += gap) {
                const index = (i + j * width) * 4; //每一个像素的位置在数组中的索引。 四个参数 左上角
                const r = data[index]; //Red value
                const g = data[index + 1];
                const b = data[index + 2]; //Blue value
                const a = data[index + 3]; //Alpha value (transparency) 是否透明? 是的话就是1 不是的
                if (r === 0 && g === 0 && b === 0 && a === 255) {
                    points.push([i, j])
                }
            }
        }
        return points;
    }
});

</script>
<style lang="scss">
#canvas {
    width: 100vw;
    height: 100vh;
    display: block;
    background: radial-gradient(#fff, #8c738c);
}
</style>